package de.lmu.ifi.pst.uwejsf.framework.process;

import java.util.HashMap;
import java.util.Map;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleScriptContext;

import de.lmu.ifi.pst.uwejsf.framework.AbstractUWEContextFactory;
import de.lmu.ifi.pst.uwejsf.framework.UWEScriptHelper;

public class OGNLSystemActionHandler implements SystemActionHandler {

	private String expression;

	protected ScriptEngine scriptEngine;

	public OGNLSystemActionHandler() {
		ScriptEngineManager manager = new ScriptEngineManager();
		scriptEngine = manager.getEngineByName("ognl");
	}

	@Override
	public String getExpression() {
		return expression;
	}

	@Override
	public void setExpression(String expression) {
		this.expression = expression;
	}

	@Override
	public Map<String, Object> execute(Map<String, Object> parameters,
			Map<String, Object> scope) {
		Map<String, Object> result = new HashMap<String, Object>();
		if (expression == null || expression.trim().length() == 0)
			return result;
		ScriptContext context = new SimpleScriptContext();
		Bindings scriptScope = context.getBindings(ScriptContext.ENGINE_SCOPE);
		// scope contains managed beans and activity object storage
		scriptScope.putAll(scope);
		scriptScope.putAll(parameters);
		scriptScope.put("uweHelper", new UWEScriptHelper(
				AbstractUWEContextFactory.getCurrentInstance()));
		scriptScope.put("uwePersistenceManager", AbstractUWEContextFactory
				.getCurrentInstance().getPersistenceManager());
		Object evaluationResult = null;
		try {
			evaluationResult = scriptEngine.eval(expression, scriptScope);
		} catch (ScriptException e) {
			throw new ProcessDataflowException(
					"Couldn't evaluate expression: " + expression + ".",
					e);
		}
		if (evaluationResult instanceof Map) {
			Map<?, ?> returnedMap = (Map<?, ?>) evaluationResult;
			for (Object key : returnedMap.keySet()) {
				if (key instanceof String)
					result.put((String) key, returnedMap.get(key));
				else
					result.put(key.toString(), returnedMap.get(key));
			}
		}
		result.put("result", evaluationResult);
		return result;
	}

}
